package com.yicheng.statistics.actor.analysis

import java.util.Date

import scala.util.Success

import org.joda.time.DateTime

import com.yicheng.statistics.actor.SaveHtaData
import com.yicheng.statistics.common.HTADB
import com.yicheng.statistics.common.RTAModel.VehicleSpeedSetting
import com.yicheng.statistics.common.TimeUtils
import com.yicheng.statistics.repo.RTAModel.VehicleSpeed
import com.yicheng.statistics.repo.cassandra.DataInfoDB

import akka.actor.Actor
import akka.actor.ActorLogging
import akka.actor.ActorRef
import akka.actor.Props
import com.yicheng.statistics.common.CommonUtils
import scala.util.Failure
import com.yicheng.statistics.repo.model.Data.AlarmInfo
import com.yicheng.statistics.repo.model.Data.DataInfo
import com.yicheng.statistics.service.HTAService
import com.carcloud.gateway.bean.data.DataVehPos
import com.yicheng.statistics.actor.AnalysisParser
import akka.actor.SupervisorStrategy.Stop

/**
 * 超速hta分析类
 */
class OverSpeed extends Actor with ActorLogging with AnalysisParser{
  
  val saveHtaDataActor:ActorRef = context.child("saveHtaData").
    getOrElse(context.actorOf(Props[SaveHtaData], "saveHtaData"))
  
  import scala.concurrent.ExecutionContext.Implicits.global
  
  type S = VehicleSpeedSetting
  def receive: Receive = {
    case (deviceId:String,deviceType:Int, analyseGroupId:Long) =>
      log.info("-----------------deviceId "+deviceId+" groupid "+analyseGroupId)
      
      var preState : PreSpeedAlarmState = PreSpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0 ,None, None)
      var speedState : SpeedAlarmState = SpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0,None, None)
    
      val speed = SpeedState(preState, speedState, deviceId, deviceType, false, false)
      
      HTADB.getVehicleSpeedSettings(analyseGroupId).map(s => 
        if( !s.headOption.isEmpty){
          parseOneDayDataInfo(deviceType, deviceId, speed, s.headOption.get, Parser _)
        }
        
      )
    case Stop =>
      //context.parent ! Stop
      log.info("overspeed stop")
      context.actorSelection("/user/daemon") ! OverSpeedStop
    case _ => log.info("OverSpeed")
  }
  
  /**
   * 分析数据超速报表
   * 从cassndra数据库取车辆数据逐条根据【超速报警设置】生成超速报表
   * 查询出的数据是grpc二进制数据，要通过接入端的解析成各种对象
   */
  def Parser(state:SpeedState, setting:VehicleSpeedSetting, dataInfos : Seq[DataInfo], isEnd:Boolean): SpeedState = {
    val now = DateTime.now()
    log.info("超速开始分析 ---分析设置"+setting)
    
    var preState : PreSpeedAlarmState = state.preState//PreSpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0 ,None, None)
    var speedState : SpeedAlarmState = state.speed//SpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0,None, None)
    
    val daySpeed =setting.speedThreshold//白天超速阀值
    val nightspeed = ((setting.nightSpeedPercent.get * setting.speedThreshold) / 100.0).round.toInt//夜间超速阈值
    val deviceId = state.deviceId
    val deviceType = state.deviceType
                 
    var currentSpeedThreshold = daySpeed//当前分析速度门限
    var preAlarm = state.preAlarm
    var alarm = state.alarm
    
    
    dataInfos.foreach( di => {
      val posData: DataVehPos = di.data_vehicle.posData.get
      val overallData = di.data_vehicle.overallData.get
      
      //夜晚的超速速度和白天不同，根据条件判断设置阀值
      if( TimeUtils.isNight(setting.nightDriveBeginTime.get, setting.nightDriveendTime.get, di.data_time)){//ni
        currentSpeedThreshold = nightspeed
      }else{
        currentSpeedThreshold = daySpeed
      }
      log.debug("OverSpeed threhsold is"+currentSpeedThreshold)
      val currentSpeed = CommonUtils.secSpeed2HourSpedd(posData.speed.getOrElse(0))
      log.info("OverSpeed speed is "+currentSpeed)
      val canAlarm = achievePredictAlarm(setting.analyseType, currentSpeedThreshold, setting.earlyWarningThreshold.getOrElse(0), currentSpeed)
      log.debug("alarm param is "+canAlarm)
      
      if(canAlarm._1 
          && preState.startTime.isEmpty 
          && speedState.startTime.isEmpty){//第一次超速信息
        
        if(canAlarm._2){
          speedState = speedState.copy(
              startTime = Some(di.data_time),
              startLat = Some(posData.latitude.get), 
              startLon = Some(posData.longitude.get), 
              speed = currentSpeed,
              maxSpeed = currentSpeed, 
              totalSpeed = currentSpeed, 
              minSpeed = currentSpeed,
              startMileage = Some(overallData.currentMileage))
          alarm = true
        }
        else{
          preState = preState.copy(
              startTime = Some(di.data_time),
              startLat = Some(posData.latitude.get), 
              startLon = Some(posData.longitude.get), 
              speed = currentSpeed,
              maxSpeed = currentSpeed, 
              totalSpeed = currentSpeed, 
              minSpeed = currentSpeed,
              startMileage = Some(overallData.currentMileage))
              
          preAlarm = true
        }
          
      }else if (canAlarm._1){//继续超速
        
        if(preAlarm) {//如果是预报警 保存预报警统计
          preState = preState.copy(
              endTime = Some(di.data_time),
              endLat = Some(posData.latitude.get),
              endLon = Some(posData.longitude.get),
              speed = currentSpeed,
              maxSpeed = if(currentSpeed > preState.maxSpeed) currentSpeed else preState.maxSpeed,
              totalSpeed = currentSpeed + preState.totalSpeed,
              minSpeed = if(currentSpeed > preState.minSpeed) preState.minSpeed else currentSpeed,
              count = preState.count+1,
              endMileage = Some(overallData.currentMileage))
        }
        
        if(alarm){//如果是报警保存报警统计
          speedState = speedState.copy(
            endTime = Some(di.data_time),
            endLat = Some(posData.latitude.get),
            endLon = Some(posData.longitude.get),
            speed = currentSpeed,
            maxSpeed = if(currentSpeed > preState.maxSpeed) currentSpeed else preState.maxSpeed,
            totalSpeed = currentSpeed + preState.totalSpeed,
            minSpeed = if(currentSpeed > preState.minSpeed) preState.minSpeed else currentSpeed,
            count = preState.count+1,
            endMileage = Some(overallData.currentMileage))
        }
        //如果达到时间阀值 
        if(TimeUtils.inTimeRang(preState.startTime.get , di.data_time, setting.timeThreshold)){
          if(preAlarm){
            val biSpeed : VehicleSpeed = VehicleSpeed(
                                              deviceType,deviceId,preState.startTime, preState.endTime, None, 
                                              Some(preState.maxSpeed),
                                              Some(preState.minSpeed),
                                              Some(preState.totalSpeed/preState.count), 
                                              Some(setting.speedThreshold), 
                                              Some(
                                                setting.analyseType match {
                                                  case 1 => "预超速报警"
                                                  case 2 => "预低速报警"
                                                }),
                                              preState.startLon,
                                              preState.startLat, 
                                              preState.endLon, 
                                              preState.endLat, 
                                              Some(setting.analyseGroupsID.toInt),
                                              setting.name,//todo 
                                              DateTime.now().toDate(), 
                                              None, 
                                              Some( preState.endMileage.get - preState.startMileage.get))
            preState = PreSpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0 ,None, None)
            preAlarm = false
            saveHtaDataActor ! biSpeed
            log.debug("overspeed save a alarm "+biSpeed)
          }
          if(alarm){
            val biSpeed : VehicleSpeed = VehicleSpeed(
                                              deviceType,deviceId,preState.startTime, preState.endTime, None, 
                                              Some(preState.maxSpeed),
                                              Some(preState.minSpeed),
                                              Some(preState.totalSpeed/preState.count), 
                                              Some(setting.speedThreshold), 
                                              Some(
                                                setting.analyseType match {
                                                  case 1 => "高速报警"
                                                  case 2 => "低速报警"
                                                }),
                                              preState.startLon,
                                              preState.startLat, 
                                              preState.endLon, 
                                              preState.endLat, 
                                              Some(setting.analyseGroupsID.toInt),
                                              setting.name,//todo 
                                              DateTime.now().toDate(), 
                                              None, 
                                              Some( preState.endMileage.get - preState.startMileage.get))
            //清理状态 进入下一次报警统计
            speedState = SpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0,None, None)
            alarm = false
            saveHtaDataActor ! biSpeed
            log.debug("overspeed save a alarm "+biSpeed)
          }
        }
      }else{
        if(preAlarm){
          preState = PreSpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0 ,None, None)
          preAlarm = false
        }
        
        if(alarm){
          speedState = SpeedAlarmState(false, None, None, None, None, None, None,0,0,0,0,0,None, None)
          alarm = false
        }
        
      }
    })
    
    if( isEnd && (preAlarm || alarm)){//这里需要报警吗 
      log.info("last data end")
    }
    
    SpeedState(preState, speedState, deviceId, deviceType,preAlarm, alarm)
  }
  
  /**
   * 判断是否达到报警标准
   * 
   * @return (预报警,报警)
   */
  def achievePredictAlarm(analyseType:Int, speed:Int , earlyWarningThreshold:Int, currentSpeed:Int):(Boolean,Boolean) = {
    analyseType match {
      case 1 =>//高速分析
        ( currentSpeed >= (speed - earlyWarningThreshold), currentSpeed >= speed)
      case 2 =>//低速分析
        (currentSpeed <= (speed + earlyWarningThreshold), currentSpeed <= speed)
    }
  }
}

/**
 * 预报警状态存储
 */
case class PreSpeedAlarmState(
    state:Boolean,
    startTime:Option[Date],
    endTime:Option[Date],
    startLat:Option[Double],
    startLon:Option[Double],
    endLat:Option[Double],
    endLon:Option[Double],
    speed:Int,
    maxSpeed:Int,
    totalSpeed:Int,
    minSpeed:Int,
    count:Int,
    startMileage:Option[Int],
    endMileage:Option[Int]
    )
   
/**
 * 报警统计
 */
case class SpeedAlarmState(
    state:Boolean,
    startTime:Option[Date],
    endTime:Option[Date],
    startLat:Option[Double],
    startLon:Option[Double],
    endLat:Option[Double],
    endLon:Option[Double],
    speed:Int,
    maxSpeed:Int,
    totalSpeed:Int,
    minSpeed:Int,
    count:Int,
    startMileage:Option[Int],
    endMileage:Option[Int]
    )
case class SpeedState(preState:PreSpeedAlarmState, speed:SpeedAlarmState, deviceId:String, deviceType:Int, preAlarm:Boolean , alarm:Boolean)
case class OverSpeedStop()